class AttackDesire{
	private var HP_LOW:int = 10;
	private var HP_MED:int = 40;
	private var HP_HIGH:int = 75;
	
	private var HIT_LOW:int = 5;
	private var HIT_MED:int = 35;
	private var HIT_HIGH:int = 75;
	
	private var DESIRE_LOW_MID:double = 25;
	private var DESIRE_MED_MID:double = 50;
	private var DESIRE_HIGH_MID:double = 75;
	
	private var _cut_off:double;
	
	//Attack Desirability Fuzzy Logic
	public function AttackDesire(cut_off:double){
		_cut_off = cut_off;
	}
	public function canAttack(player_hp, hit_chance):boolean{
		// Array to store HP calculation
		var hpList:Array = new Array();
		hpList.push(leftGradeMembership(player_hp, HP_LOW, HP_MED));			// hp low
		hpList.push(triangularMembership(player_hp, HP_LOW, HP_HIGH, HP_MED)); // hp med
		hpList.push(rightGradeMembership(player_hp, HP_MED, HP_HIGH));			// hp high
		
		// Array to store Hit Chance calculation
		var hitList:Array = new Array();
		hitList.push(leftGradeMembership(hit_chance, HIT_LOW, HIT_MED));			// hit low
		hitList.push(triangularMembership(hit_chance, HIT_LOW, HIT_HIGH, HIT_MED));	// hit med
		hitList.push(rightGradeMembership(hit_chance, HIT_MED, HIT_HIGH));			// hit high
			
		var desireList:Array = new Array();
		
		for(var i=0; i<hpList.length; i++){
			for(var j=0; j<hitList.length; j++){
				desireList.push(findMinimum(hpList[i], hitList[j]));
			}
		}		
		
		var undesirable = findMaximum(desireList[0], desireList[1]);
		var desirable = findMaximum(desireList[2], findMaximum(desireList[3], findMaximum(desireList[4],desireList[6])));
		var very_desirable = findMaximum(desireList[5], findMaximum(desireList[7], desireList[8]));
			
		var desirability = ((undesirable*DESIRE_LOW_MID)+(desirable*DESIRE_MED_MID)+(very_desirable*DESIRE_HIGH_MID))/(undesirable+desirable+very_desirable);
		
		//Debug.Log(undesirable+" | "+desirable+" | "+very_desirable+" | "+desirability);
		//Debug.Log(desireList[2]+" | "+desireList[3]+" | "+desireList[4]+" | "+desireList[6]);
		
		if(desirability >= _cut_off)
			return true;
		else
			return false;
	}
	private function findMinimum(num1:double, num2:double):double{
		if(num1 < num2) return num1;
		return num2;
	}
	private function findMaximum(num1:double, num2:double):double{
		if(num1 > num2) return num1;
		return num2;
	}
	private function leftGradeMembership(fuzzy_value:double, lessthan_value:int, morethan_value:int){
		if(fuzzy_value <= lessthan_value) {
			return 1;
		}
		if(fuzzy_value >= morethan_value) {
			return 0;
		}		
		
		// If value lies in the middle
		var gradient = calcGradient(1.0,0.0, lessthan_value, morethan_value);
		var constant = 1.0-(gradient*lessthan_value); 
		
		return (gradient*fuzzy_value) + constant;
	}
	private function rightGradeMembership(fuzzy_value:double, lessthan_value:int, morethan_value:int){
		if(fuzzy_value <= lessthan_value) {
			return 0;
		}
		if(fuzzy_value >= morethan_value) {
			return 1;
		}		
		
		// If value lies in the middle
		var gradient = calcGradient(0.0,1.0, lessthan_value, morethan_value);
		var constant = 0.0-(gradient*lessthan_value); 
		
		return (gradient*fuzzy_value) + constant;
	}
	private function triangularMembership(fuzzy_value:double, lessthan_value:int, morethan_value:int, max_value:int){
		if(fuzzy_value <= lessthan_value) 
			return 1;
		if(fuzzy_value >= morethan_value) 
			return 0;
		
		var gradient:double;
		var constant:double;
		// If value lies on right triangle
		if(fuzzy_value >= max_value){
			// If value lies in the middle
			gradient = calcGradient(0.0,1.0, morethan_value, max_value);
			constant = 1.0-(gradient*max_value); 
		}else{		
			// If value lies in the left triangle
			gradient = calcGradient(0.0,1.0, lessthan_value, max_value);
			constant = 0.0-(gradient*lessthan_value); 
		}
	
		return (gradient*fuzzy_value) + constant;
	}
	private function calcGradient(y1:double, y2:double, x1:double, x2:double):double{
		return (y2-y1)/(x2-x1);
	}
}